#include "stm32f10x.h"                  // Device header
#include "Delay.h"

//PA6
#define DHT11_PORT GPIOA
#define DHT11_PIN GPIO_Pin_12
#define DHT11_RCC RCC_APB2Periph_GPIOA

void dht11_init(void)
{
		RCC_APB2PeriphClockCmd(DHT11_RCC, ENABLE); 
}

static void DHT11_OUT(int x)
{
	GPIO_InitTypeDef GPIO_InitStructure; 
	GPIO_InitStructure.GPIO_Pin = DHT11_PIN; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
	
	if(x)
		GPIO_SetBits(DHT11_PORT, DHT11_PIN); 
	else
		GPIO_ResetBits(DHT11_PORT, DHT11_PIN); 
}

static int DHT11_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; 
	GPIO_InitStructure.GPIO_Pin = DHT11_PIN; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 
	GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
	
	return GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN); 
}

static int read_bit()
{
	int i = 0;
	while(DHT11_IN());
	while(!DHT11_IN());//吃低电平
	
#if 1
	Delay_us(40);

	if(DHT11_IN())
		return 1;
	else
		return 0;
#else
	while(DHT11_IN())
	{
		Delay_us(1);
		i++;		
	}
	
	if(i>40)
		return 1;
	else
		return 0;
#endif
}

int dht11_read(unsigned char *w, unsigned char *h)
{
	//1. PA6输出//2. 握手
	DHT11_OUT(1);
	Delay_ms(10);
	DHT11_OUT(0);
	Delay_ms(20);
	DHT11_OUT(1);
	Delay_us(30);

	//4. 理解握手
	int i = 0;
	while(DHT11_IN())//吃高电平
	{
		Delay_us(1);
		i++;
		if(i > 40)//对方没回复
			return -1;
	}
	
	while(!DHT11_IN())//吃di电平
	{
		i = 0;
		Delay_us(1);
		i++;
		if(i > 90)//对方没回复
			return -2;
	}
	
	while(DHT11_IN());//吃高电平
	
	//5. 读入40bit
	unsigned char buf[5] = {0};
	for(int i = 0; i<5; i++)
	{
		for(int j=0; j<8; j++)
		{
			buf[i] |= (read_bit() << (7-j));
		}
	}
	//6. 校验
	if(buf[4] == buf[0]+buf[1]+buf[2]+buf[3])
	//7. 返回
	{	
		*w = buf[2];
		*h = buf[0];
		return 0;
	}
	return -3;
}
